
#include "RoomGfx.h"
#include "StimDee.h"
#include <QtGui>
#include "Spreadsheet.h"
#include <vector>
#include <string>
using namespace std;

//Dee stimulis

#include "PhiGamma.h"
#include "Matrices.h"
//#include "CVSElapsedTimer.h"
#include "RoomData.h"

#include <QtOpenGL\QtOpenGL>
#include <gl\GLU.h>

#include "Helper.h"
#include "Disturbance.h"
//Stimulis

class CDisturbance;
using namespace Stims;

CRoomGfx::CRoomGfx(CData* pData_/*=NULL*/ )
:CGfx(pData_)
{
    _pRoomData = dynamic_cast<CRoomData*>(pData_);
    _bShowScene = false;
}

CRoomGfx::~CRoomGfx(void)
{

}

void CRoomGfx::LoadParametersFromScript()
{
    _nControlOrder    = _pRoomData->GetRunScript()(_pRoomData->trialIdx(),0);
    _dVelocityForward = _pRoomData->GetRunScript()(_pRoomData->trialIdx(),1);
    _nNumDots         = _pRoomData->GetRunScript()(_pRoomData->trialIdx(),3);
}
void CRoomGfx::initStimuli(const vector<int>& vConds_)
{
    _vpcStimDee.clear();
    for (unsigned int i=0; i<vConds_.size(); i++)
    {
        switch(vConds_[i])
        {
        case 1: // T1G texture ground 
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimNDotTexture(false)));
            boost::dynamic_pointer_cast<CStimNDotTexture>(_vpcStimDee[i])->SetTexFileName()    = _pRoomData->texFileName()[0];
        case 2: // T1GC texture ground + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimNDotTexture(true)));
            boost::dynamic_pointer_cast<CStimNDotTexture>(_vpcStimDee[i])->SetTexFileName()    = _pRoomData->texFileName()[0];
            break;
        case 3: // T2G texture ground 
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimNDotTexture(false)));
            boost::dynamic_pointer_cast<CStimNDotTexture>(_vpcStimDee[i])->SetTexFileName()    = _pRoomData->texFileName()[1];
            break;
        case 4: // T2GC texture ground + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimNDotTexture(true)));
            boost::dynamic_pointer_cast<CStimNDotTexture>(_vpcStimDee[i])->SetTexFileName()    = _pRoomData->texFileName()[1];
            break;
        case 11: // UGZ uniform ground w.r.t. z
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(false)));
            break;
        case 111: // UGZF uniform ground w.r.t. z with limited lifetime
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(false)));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 12: // UGZC uniform ground w.r.t. z + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(true)));
            break;
        case 121: // UGZF uniform ground w.r.t. z with limited lifetime
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(true)));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 13: // UGZSp uniform ground w.r.t. z Sphere
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(false,Stims::Sphere)));
            break;
        case 14: // UGZCSp uniform ground w.r.t. z Sphere + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(true,Stims::Sphere)));
            break;
        case 15: // UGZDi uniform ground w.r.t. z Disc
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(false,Stims::Disc)));
            break;
        case 16: // UGZCDi uniform ground w.r.t. z Disc + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(true,Stims::Disc)));
            break;
        case 21:// UG uniform ground
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(false)));
            break;
        case 211:// UG uniform ground with limited lifetime
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(false)));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 22:// UGC uniform ground + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(true)));
            break;
        case 221:// UG uniform ground + ceiling with limited lifetime
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(true)));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 23:// UGSp uniform ground sphere
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(false,Stims::Sphere)));
            break;
        case 24:// UGCSp uniform ground sphere + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(true,Stims::Sphere)));
            break;
        case 25:// UGDi uniform ground Disc
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(false,Stims::Disc)));
            break;
        case 26:// UGDi uniform ground Disc + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(true,Stims::Disc)));
            break;
        case 31:// DG de-perspective ground
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(false)));
            break;
        case 311:// DG de-perspective ground
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(false)));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 32:// DGC de-perspective ground + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(true)));
            break;
        case 321:// DGC de-perspective ground + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(true)));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 33:// DGSp de-perspective ground sphere
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(false,Stims::Sphere)));
            break;
        case 34:// DGCSp de-perspective ground sphere + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(true,Stims::Sphere)));
            break;
        case 35:// DGDi de-perspective ground Disc
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(false,Stims::Disc)));
            break;
        case 36:// DGCDi de-perspective ground Disc + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(true,Stims::Disc)));
            break;
        case 41:// UCl uniform cloud
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloudUniform()));
            break;
        case 411:// UClF uniform cloud
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloudUniform()));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 42:// UClSp uniform cloud sphere
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloudUniform(Stims::Sphere)));
            break;
        case 43:// UClZ uniform cloud w.r.t. z
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloud()));
            break;
        case 431:// UClZ uniform cloud w.r.t. z
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloud()));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 44:// UClZSp unifrom cloud w.r.t. z sphere
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloud(Stims::Sphere)));
            break;
        case 45:// UClF unifrom with limited life time
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotCloud()));
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDotLifeTime() = 6;
            break;
        case 51:// SG solid ground
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimNDotSolid(false)));
            break;
        case 52:// SGC solid ground + ceiling
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimNDotSolid(true)));
            break;
        case 61:// UGCl uniform ground equated cloud 
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(false)));
            boost::dynamic_pointer_cast<CStimDotGroundUniform>(_vpcStimDee[i])->SetEquatedCloud() = true;
            break;
        case 62:// UGCCl uniform ground + ceiling equated cloud 
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundUniform(true)));
            boost::dynamic_pointer_cast<CStimDotGroundUniform>(_vpcStimDee[i])->SetEquatedCloud() = true;
            break;
        case 71:// UGZCl uniform ground w.r.t. z equated cloud
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(false)));
            boost::dynamic_pointer_cast<CStimDotGround>(_vpcStimDee[i])->SetEquatedCloud() = true;
            break;
        case 72:// UGZCCl uniform ground w.r.t. z + ceiling equated cloud
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGround(true)));
            boost::dynamic_pointer_cast<CStimDotGround>(_vpcStimDee[i])->SetEquatedCloud() = true;
            break;
        case 81:// DGCl de-perspective ground equated cloud
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(false)));
            boost::dynamic_pointer_cast<CStimDotGroundDeperspective>(_vpcStimDee[i])->SetEquatedCloud() = true;
            break;
        case 82:// DGCCl de-perspective ground + ceiling equated cloud
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimDotGroundDeperspective(true)));
            boost::dynamic_pointer_cast<CStimDotGroundDeperspective>(_vpcStimDee[i])->SetEquatedCloud() = true;
            break;
        case 91:// T" target moving
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimTargetMoving(Stims::PostSphere)));
            break;
        case 92:// TP target post fixed
            _vpcStimDee.push_back(boost::shared_ptr<CStimBase>(new CStimTargetFixed(Stims::Post)));
            break;
        }

        if(_vpcStimDee.empty()) continue;

        // set needed variables
        // current stimulus derives of CStimDot
        // including: CStimDotCloud, CStimDotCloudUniform, CStimDotGround,
        // CStimDotGroundUniform, CStimDotGroundDeperspective
        if (boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i]) != 0) 
        {
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetFOVy()       = _pRoomData->gfxFOVy();
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetAspectRatio()= _pRoomData->gfxAspectRatio();
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetNearPlane()  = _pRoomData->gfxNear();
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetFarPlane()   = _pRoomData->gfxFar();
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetEyeHeight()  = _pRoomData->eyeHeight();
            boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetNPoint()     = _nNumDots; // input from script file

            switch(boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->ObjType())
            {
            case Stims::GLpoint:
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetPointColor() = vector<double>(_pRoomData->dotColor());
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetPointSize()      =_pRoomData->dotSize();
                break;

            case Stims::Sphere:
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetSphereColor() = vector<double>(_pRoomData->dotColor());
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetSphereRadius()   = _pRoomData->sphereDiscRadius();
                break;
            case Stims::Disc:
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDiscColor() = vector<double>(_pRoomData->dotColor());
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetDiscRadius()   = _pRoomData->sphereDiscRadius();
                break;
            case Stims::Post:
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetPostColor() = vector<double>(_pRoomData->dotColor());
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetPostRadius()   = _pRoomData->sphereDiscRadius();
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetPostHeight()   = _pRoomData->postHeight();
                break;
            }

            if (boost::dynamic_pointer_cast<CStimDotGroundUniform>(_vpcStimDee[i]) == 0 && boost::dynamic_pointer_cast<CStimDotCloudUniform>(_vpcStimDee[i]) == 0) // Uniform density stimuli confined to 1 Area, setting NArea would throw
                boost::dynamic_pointer_cast<CStimDot>(_vpcStimDee[i])->SetNArea()      = 50;
        }
        // current stimulus derives of CStimNDot
        // including: CStimNDotSolid, CStimNDotTexture
        else if (boost::dynamic_pointer_cast<CStimNDot>(_vpcStimDee[i]) != 0) // current stimulus derives of CStimNDot
        {
            boost::dynamic_pointer_cast<CStimNDot>(_vpcStimDee[i])->SetEyeHeight() = _pRoomData->eyeHeight();
            if (boost::dynamic_pointer_cast<CStimNDotTexture>(_vpcStimDee[i]) != 0) 
            {
                boost::dynamic_pointer_cast<CStimNDotTexture>(_vpcStimDee[i])->SetTextureScale()   = _pRoomData->texScale();
            }
            else if (boost::dynamic_pointer_cast<CStimNDotSolid>(_vpcStimDee[i]) != 0)
            {
                boost::dynamic_pointer_cast<CStimNDotSolid>(_vpcStimDee[i])->SetGroundColor()    = vector<double>(_pRoomData->groundColor());
            }
        }
        // current stimulus derives of CStimTarget
        // including: CStimTargetMoving, CStimTargetFixed
       /*
         else if (boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i]) != 0)
                {
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetEyeHeight()    = _pRoomData->eyeHeight();
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetPostHeight()    = _pRoomData->postHeight();
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetPostPosition()    = vector<double>(_pRoomData->targetPostPosition());
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetPostColor()    = vector<double>(_pRoomData->targetPostColor());
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetSphereColor()    = vector<double>(_pRoomData->targetColor());
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetPostRadius()    = _pRoomData->targetRadius();
                    boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetSphereRadius()    = _pRoomData->targetRadius();
        
                    / *
                    if (boost::dynamic_pointer_cast<CStimTargetFixed>(_vpcStimDee[i]) != 0)
                                {
                                    boost::dynamic_pointer_cast<CStimTargetFixed>(_vpcStimDee[i])->SetPostColor()    = vector<double>(_pRoomData->targetPostColor());
                                    boost::dynamic_pointer_cast<CStimTargetFixed>(_vpcStimDee[i])->SetPostRadius()    = _pRoomData->targetRadius();
                                    if(boost::dynamic_pointer_cast<CStimTargetMoving>(_vpcStimDee[i]) != 0)
                                    {
                                        boost::dynamic_pointer_cast<CStimTargetMoving>(_vpcStimDee[i])->SetSphereColor()    = vector<double>(_pRoomData->targetColor());
                                        boost::dynamic_pointer_cast<CStimTargetMoving>(_vpcStimDee[i])->SetCylinderColor()    = vector<double>(_pRoomData->targetPostColor());
                                        boost::dynamic_pointer_cast<CStimTargetMoving>(_vpcStimDee[i])->SetPostPosition()[2]    = _pRoomData->gfxFar()-_pRoomData->infrontofFar();
                                        boost::dynamic_pointer_cast<CStimTargetMoving>(_vpcStimDee[i])->SetSphereRadius()    = _pRoomData->targetRadius();
                                        boost::dynamic_pointer_cast<CStimTargetMoving>(_vpcStimDee[i])->SetCylinderRadius()    = _pRoomData->targetRadius()/2;
                                    }
                                }* /
                    
                }*/
        // if this stimulus is made of Objects (so this will be false for e.g. StimTarget stimuli
        if (boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i]) != 0) 
        {
            boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetTargetPosition()    = vector<double>(_pRoomData->targetPostPosition());
            boost::dynamic_pointer_cast<CStimTarget>(_vpcStimDee[i])->SetEyeHeight()       = _pRoomData->eyeHeight();

            switch (boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->ObjType())
            // set object-specific stuff
            {
            case Stims::Sphere:

                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetSphereColor()    =   _pRoomData->targetColor();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetSphereRadius()   =   _pRoomData->targetRadius();
                break;

            case Stims::Post:

                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetPostColor()      =   _pRoomData->targetPostColor();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetPostRadius()     =   _pRoomData->postRadius();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetPostHeight()     =   _pRoomData->postHeight();
                break;

            case Stims::PostSphere:

                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetPostColor()      =   _pRoomData->targetPostColor();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetPostRadius()     =   _pRoomData->postRadius();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetPostHeight()     =   _pRoomData->postHeight();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetSphereColor()    =   _pRoomData->targetColor();
                boost::dynamic_pointer_cast<CStimObj>(_vpcStimDee[i])->SetSphereRadius()   =   _pRoomData->targetRadius();
                break;
            }
            // TODO: if object has a texture on it, set texture
        }
        _vpcStimDee[i]->Reset();
    }
    return;
}
void CRoomGfx::renderObj()
{
    for (unsigned int i=0; i<_vpcStimDee.size(); i++)
    {
        //if (_pRoomData->timeIdx()!=_nLastFrameTimeIdx)
        _vpcStimDee[i]->Update(_pRoomData->eyePath().GetRow(_pRoomData->timeIdx()).Transpose(),-_pRoomData->Yaw()(_pRoomData->timeIdx()));
        _nLastFrameTimeIdx = _pRoomData->timeIdx();
        _vpcStimDee[i]->Draw();
    }
    return;
}

void CRoomGfx::renderBirdView()
{
    CMatrix<double> mEye,mGazingPoint;
    _pRoomData->computeEyePositionAndGazing(mEye,mGazingPoint,_pRoomData->timeIdx());

    CGfx::renderBirdView();
    
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLineWidth(2.f);
    //render gazing yellow
    glColor3d(1.,1.,0.);
    glBegin(GL_LINES);
        glVertex3d(mEye(0),mEye(1),mEye(2));
        glVertex3d(mGazingPoint(0),mGazingPoint(1),mGazingPoint(2));
    glEnd();

    //render heading disturbance red
    glColor3d(1,0,0);
    glBegin(GL_LINE_STRIP);
    for(int i=0;i<_pRoomData->timeIdx();i++)
    {
        mEye = _pRoomData->eyePath().GetRow(i);
        double dDx = _pRoomData->phiGamma(_nControlOrder)->GetOutputValues()(i,0);
        glVertex3d(dDx,0,mEye(2));
    }
    glEnd();

    //render gazing disturbance blue
    glColor3d(0,0,1);
    glBegin(GL_LINE_STRIP);
    for(int i=0;i<_pRoomData->timeIdx();i++)
    {
        mEye = _pRoomData->eyePath().GetRow(i);
        double dDx = _pRoomData->phiGamma(_nControlOrder)->GetOutputValues()(i,1);
        glVertex3d(dDx,0,mEye(2));
    }
    glEnd();

    //render path green
    glColor3d(0,1,0);
    glBegin(GL_LINE_STRIP);
    for(int i=0;i<_pRoomData->timeIdx();i++)
    {
        mEye = _pRoomData->eyePath().GetRow(i);
        glVertex3d(mEye(0),0,mEye(2));
    }
    glEnd();
    
    glPopMatrix();
    return;
}

void CRoomGfx::updateObserver(int nCurrentFrame_)
{
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    CMatrix<double> mEye,mGazingPoint,mUpVec;
    _pRoomData->computeEyePositionAndGazing(mEye,mGazingPoint,nCurrentFrame_);
    mUpVec  = _pRoomData->ObserverUpVec().GetRow(nCurrentFrame_);
    //_pRoomData->PerFramePrecompute(nCurrentFrame_);

    //if(mEye.Len()==0) return;
    //if(mGazingPoint.Len()==0) return;

    gluLookAt(
        mEye(0),mEye(1),mEye(2),
        mGazingPoint(0),mGazingPoint(1),mGazingPoint(2),
        0,1,0);
       //mUpVec(0),mUpVec(1),mUpVec(2));
    return;
}


void CRoomGfx::updateBirdObserver(int nCurrentFrame_)
{
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    CMatrix<double> mEye,mDirect;
    if(nCurrentFrame_>=_pRoomData->eyePath().Rows())
    {
        mEye = _pRoomData->eyePath().GetRow(_pRoomData->eyePath().Rows()-1);
    }
    else
    {
        mEye = _pRoomData->eyePath().GetRow(nCurrentFrame_);
        mDirect = _pRoomData->observerDirect().GetRow(nCurrentFrame_);
    }
    if(mEye.Len()==0)
        return;

    gluLookAt(
        0,10,mEye(2)+1,
        0,0,mEye(2)+2,
        0,1,0
        );
}

void CRoomGfx::updateStatus()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    switch (_eCurrExptState)
    {
    case BeforeRun:
        {
            if (_pData->allTrialsFinished())
            {
                // end of last trial, quit program
                _eCurrExptState = ExpEnd;
                break;
            } 
            LoadParametersFromScript();
            // precompute before every trial
            _pData->precomputeEachTrial();
            _pData->setTimer() = 0;
            vector<int> vConds; 
            _pRoomData->parser(_pRoomData->conditionScript()[_pRoomData->trialIdx()],&vConds);
            initStimuli(vConds);
            initDisplayList();
            setExptState() = OnBreak;

            _nLastFrameTimeIdx = -1; //the last frame is negative for the first frame to run update function
            //at least once.
            _bTriggerLastFrame = true; // set it as true to avoid the first.
            // time of pressing trigger down when starting the trial.
            setShowScene() = false;   // the initial display doesn't contain tunnel.
        } 
        break;
    case OnBreak:
        {
            //renderBreak();
            while(!_pData->preRunFinished())
            {
                _pData->updateOutput(1);
                offlineRender();
                _pData->setTimeIdx()++;
            }

            _pData->updateOutput(1);
            renderNormalView();

            //because disturbances were updated for every trial
            if(_pData->flyBox())
            {
                if(_pData->CheckForTriggerHelper())
                {
                    _eCurrExptState = NormalView;
                }
            }
        }
        break;
    case NormalView:
        {
            if (_pData->allTrialsFinished()||_pData->trialFinished())
            {
                _eCurrExptState = AfterRun;
            }
            else
            {    
                _pData->updateOutput();
                renderNormalView();
                _pData->setTimeIdx()++;
            }
        }
        break;
    case BirdView:
        {
            if (_pData->allTrialsFinished()||_pData->trialFinished())
            {
                _eCurrExptState = AfterRun;
            }
            else
            {    
                _pData->updateOutput();
                renderBirdView();
                _pData->setTimeIdx()++;
            }
            break;
        }
    case AfterRun:
        {
            
            _pData->afterCompute();
            if (_pData->allTrialsFinished())
            {
                // end of last trial, quit program
                _eCurrExptState = ExpEnd;
            } 
            else
            {
#if !_DEBUG
                // in release mode:
                //experiment canceled no data will be saved 
                if(_pData->trialFinished())
                    _pData->saveToFile();
#else
                // in debug mode:
                //save anyway
                _pData->saveToFile();
#endif
                _pData->setTrialIdx()++;
                _eCurrExptState = BeforeRun;
            }
        }
        break;
    case ExpEnd:
        break;
    }
}

void CRoomGfx::initDisplayList()
{
    ;
}